//
// Created by lymk on 2022/2/26.
//

#ifndef SOFTRENDER_RENDERPIPELINE_H
#define SOFTRENDER_RENDERPIPELINE_H
#include "Buffer.h"
#include "FrameBuffer.h"
#include "Shader/IShader.h"
#include "Model/IMesh.h"
#include "GameTimer.h"
#include "Camera.h"

struct Object{
    IMesh* mesh;
    glm::mat4 transformMatrix;
public:
    Object(IMesh* m);
    glm::mat4 GetModelMatrix() const;
    void Translate(glm::vec3 distance);
    void RotateX(float degree);
    void RotateY(float degree);
    void RotateZ(float degree);
    void Scale(glm::vec3 s);
};

class RenderPipeline {
    FrameBuffer* frameBuffer;
    IShader* shader;
    Camera* camera;
    std::vector<Object> world;
    int32_t screenHeight = 800;
    int32_t screenWeight = 600;
public:
    bool InsideTriangle(glm::vec2 pos,const std::vector<glm::vec2>& triangle);
    glm::vec3 ComputeBarycentric(glm::vec2 pos,const std::vector<glm::vec2>& triangle);
    glm::vec3 Interpolation(glm::vec3 coord,glm::vec4 ZBuffer,const std::vector<glm::vec3>& value);
    glm::vec2 Interpolation(glm::vec3 coord,glm::vec4 ZBuffer,const std::vector<glm::vec2>& value);
    glm::vec4 Interpolation(glm::vec3 coord,glm::vec4 ZBuffer,const std::vector<glm::vec4>& value);
    float GetZBuffer(glm::vec3 coord,float Z1,float Z2,float Z3);

    void Initialize(int w,int h);
    void DrawObject(const Object& object);
    void DrawTriangle(int triIdx,const std::vector<int>& idx,const std::vector<VertexIn>& vertexList);
    Buffer* GetRenderBuffer();
    void Tick(GameTimer* timer);
    void Clear();

    void AddObject(Object o);
    void AddPointLight(Light l);
};


#endif //SOFTRENDER_RENDERPIPELINE_H
